package com.chinatechstar.admin.service.impl;

import com.chinatechstar.admin.entity.JsonObj;
import com.chinatechstar.admin.entity.SysDict;
import com.chinatechstar.admin.entity.SysOrg;
import com.chinatechstar.admin.entity.TkmSysEx;
import com.chinatechstar.admin.mapper.SysOrgMapper;
import com.chinatechstar.admin.service.TkmRemoteUserService;
import com.chinatechstar.admin.service.TkmSysExService;
import com.chinatechstar.admin.utils.Utils;
import com.chinatechstar.component.commons.entity.MPage;
import com.chinatechstar.component.commons.result.ActionResult;
import com.chinatechstar.component.commons.result.ListResult;
import com.chinatechstar.component.commons.service.BaseService;
import com.chinatechstar.component.commons.supports.PageData;

import com.chinatechstar.component.commons.utils.UuidUtil;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import com.chinatechstar.component.commons.utils.CollectionUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;

import com.chinatechstar.admin.entity.SysUser;
import com.chinatechstar.admin.mapper.SysRoleMapper;
import com.chinatechstar.admin.mapper.SysUserMapper;
import com.chinatechstar.admin.service.SysUserService;
import com.chinatechstar.component.commons.result.PaginationBuilder;
import com.chinatechstar.component.commons.utils.CurrentUserUtils;
import com.chinatechstar.component.commons.utils.SequenceGenerator;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.transaction.support.DefaultTransactionDefinition;

/**
 * 用户信息的业务逻辑实现层
 *
 * @版权所有 上海至界信息科技有限公司
 */
@Service
@Transactional
public class SysUserServiceImpl implements SysUserService {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    private static SequenceGenerator sequenceGenerator = new SequenceGenerator();

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysOrgMapper sysOrgMapper;
    @Autowired
    private TkmRemoteUserService remoteUserService;
    @Autowired
    private TkmSysExService tkmSysExService;
    @Autowired
    private DataSourceTransactionManager transactionManager;


    /**
     * 查询用户分页
     */
    @Override
    public Map<String, Object> querySysUser(Integer currentPage,
                                            Integer pageSize,
                                            String username,
                                            String status,
                                            String sorter) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("username", username);
        paramMap.put("tenantCode",
                     CurrentUserUtils
                         .getOAuth2AuthenticationDetailsInfo()
                         .get("tenantCode"));// 当前用户的租户编码
        if (StringUtils.isNotBlank(status)) {
            String[] statusArray = status.split(",");
            paramMap.put("statusList", (Short[]) ConvertUtils.convert(statusArray, Short.class));
        }
        if (StringUtils.isNotBlank(sorter)) {
            String sort = sorter.substring(0, sorter.lastIndexOf('_'));
            String sequence =
                "ascend".equals(sorter.substring(sorter.lastIndexOf('_') + 1)) ? "ASC" : "DESC";
            paramMap.put("sort", sort);
            paramMap.put("sequence", sequence);
        } else {
            paramMap.put("sort", "createTime");
            paramMap.put("sequence", "DESC");
        }
        Page<Object> page = PageHelper.startPage(currentPage, pageSize);
        List<LinkedHashMap<String, Object>> resultList = sysUserMapper.querySysUser(paramMap);

        String roleData = sysRoleMapper.queryRoleData("sysuser",
                                                      CurrentUserUtils
                                                          .getOAuth2AuthenticationDetailsInfo()
                                                          .get("name"));
        String[] roleDataArray = roleData == null ? null : roleData.split(",");
        if (roleDataArray != null && roleDataArray.length > 0) {// 处理数据权限
            return PaginationBuilder.buildResult(CollectionUtils.convertFilterList(resultList,
                                                                                   roleDataArray),
                                                 page.getTotal(),
                                                 currentPage,
                                                 pageSize);
        } else {
            return PaginationBuilder.buildResult(resultList,
                                                 page.getTotal(),
                                                 currentPage,
                                                 pageSize);
        }
    }

    /**
     * 根据参数查询用户列表
     */
    @Override
    public List<LinkedHashMap<String, Object>> querySysUser(Map<String, Object> paramMap) {
        return sysUserMapper.querySysUser(paramMap);
    }

    /**
     * 查询用户的导出数据列表
     */
    @Override
    public List<LinkedHashMap<String, Object>> querySysUserForExcel(Map<String, Object> paramMap) {
        if (paramMap.get("status") != null && StringUtils.isNotBlank(paramMap
                                                                         .get("status")
                                                                         .toString())) {
            String[] statusArray = paramMap
                .get("status")
                .toString()
                .split(",");
            paramMap.put("statusList", (Short[]) ConvertUtils.convert(statusArray, Short.class));
        }
        List<LinkedHashMap<String, Object>> resultList = new ArrayList<>();
        List<LinkedHashMap<String, Object>> dataList = sysUserMapper.querySysUser(paramMap);
        if (!org.apache.commons.collections.CollectionUtils.isEmpty(dataList)) {
            dataList.forEach(map -> {
                LinkedHashMap<String, Object> entity = new LinkedHashMap<>();
                for (Entry<String, Object> entry : map.entrySet()) {
                    String key = entry.getKey();
                    Object value = entry.getValue();
                    if ("status".equals(key)) {
                        value = Short.valueOf(value.toString()) == 1 ? "正常" : "禁用";
                    }
                    entity.put(key, value);
                }
                resultList.add(entity);
            });
        }
        return resultList;
    }

    /**
     * 根据用户ID查询用户名的数据列表
     */
    @Override
    public List<LinkedHashMap<String, Object>> queryUsername(Long[] id) {
        return sysUserMapper.queryUsername(id);
    }

    /**
     * 根据用户名查询用户ID的数据列表
     */
    @Override
    public List<Long> querySysUserId(String[] username) {
        return sysUserMapper.querySysUserId(username);
    }

    /**
     * 新增用户
     */
    @Override
    public void insertSysUser(SysUser sysUser) {
        Integer existing = sysUserMapper.getSysUserByIdentification(sysUser
                                                                        .getUsername()
                                                                        .trim(),
                                                                    sysUser
                                                                        .getMobile()
                                                                        .trim());
        if (existing != null && existing > 0) {
            throw new IllegalArgumentException("用户名或手机号已存在");
        }
        long userId = sequenceGenerator.nextId();
        // 如果是null,默认把status调整为1
        if (sysUser.getStatus() == null) {
            sysUser.setStatus((short) 1);
        }
        sysUser.setId(userId);
        sysUser.setPassword(encoder.encode(sysUser.getPassword()));
        sysUser.setTenantCode(CurrentUserUtils
                                  .getOAuth2AuthenticationDetailsInfo()
                                  .get("tenantCode"));// 当前用户的租户编码

        sysUserMapper.insertSysUser(sysUser);
        for (int i = 0; i < sysUser.getRoleId().length; i++) {
            sysRoleMapper.insertSysRoleUser(sequenceGenerator.nextId(),
                                            sysUser.getRoleId()[i],
                                            userId);
        }

        // 像扩展信息表（），中加入数据
        TkmSysEx sysEx = new TkmSysEx();
        sysEx.setId(UuidUtil.get32UUID());
        sysEx.setBillNo(sysUser.getPassword());
        sysEx.setSourceId(sysUser
                              .getId()
                              .toString());
        sysEx.setCreateDatetime(new Date(System.currentTimeMillis()));
        tkmSysExService.insert(sysEx);

        logger.info("用户已新增： {}", sysUser.getUsername());
    }

    /**
     * 将对应的角色授予用户
     */
    @Override
    public void insertRoleIdUserId(Long[] roleId, Long userId) {
        Set<Long> roleIdSet = new HashSet<>();
        List<Long> roleList = sysRoleMapper.queryRoleIdByUserId(userId);
        for (int i = 0; i < roleList.size(); i++) {
            roleIdSet.add(roleList.get(i));
        }
        for (int x = 0; x < roleId.length; x++) {
            roleIdSet.add(roleId[x]);
        }
        sysRoleMapper.deleteSysRoleUser(userId, null);
        Iterator<Long> iterator = roleIdSet.iterator();
        while (iterator.hasNext()) {
            Long roleIdData = iterator.next();
            sysRoleMapper.insertSysRoleUser(sequenceGenerator.nextId(), roleIdData, userId);
        }
    }

    /**
     * 编辑用户
     */
    @Override
    public JsonObj updateSysUser(SysUser sysUser) {

        //2.获取事务定义
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        //3.设置事务隔离级别，开启新事务
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        //4.获得事务状态，相当于开启事物
        TransactionStatus transactionStatus = transactionManager.getTransaction(def);

        List<String> errors = Utils.validateSysUserData(sysUser);
        if (errors.size() > 0) {
            return JsonObj.error(errors
                                     .stream()
                                     .collect(Collectors.joining("|")));
        }

        Integer existing = sysUserMapper.getSysUserByIdEmailMobile(sysUser.getId(),
                                                                   sysUser.getMobile().trim());
        if (existing != null && existing > 0) {
            errors = new ArrayList<>();
            errors.add("用户名或手机号已存在");
            return JsonObj.error(errors
                                     .stream()
                                     .collect(Collectors.joining("|")));
        }
        String password = sysUser.getPassword();
        if (StringUtils.isNotBlank(password)) {
            sysUser.setPassword(encoder.encode(password));
        }
        // 检查当前用户的orgId是否有要变更
        SysUser source = sysUserMapper.selectById(sysUser.getId());
        long orgId = source.getOrgId();
        long nOrgId = sysUser.getOrgId();
        sysUserMapper.updateSysUser(sysUser);
        // 重新设置用户的角色
        sysRoleMapper.deleteSysRoleUser(sysUser.getId(), null);
        for (int i = 0; i < sysUser.getRoleId().length; i++) {
            sysRoleMapper.insertSysRoleUser(sequenceGenerator.nextId(),
                                            sysUser.getRoleId()[i],
                                            sysUser.getId());
        }
        logger.info("用户已编辑： {}", sysUser.getUsername());

        // 提交已做的修改
        transactionManager.commit(transactionStatus);

        // 更新扩展信息表中的数据
        String userId = String.valueOf(sysUser.getId());
        // 更新系统扩展信息表中的数据
        TkmSysEx sysEx = tkmSysExService.findBySourceId(userId);
        if (sysEx != null) {
            // 删除旧数据
            tkmSysExService.deleteBySourceId(userId);
            sysEx.setSourceId(userId);
            sysEx.setBillNo(password);
            // 创建新数据
            tkmSysExService.insert(sysEx);
        }
        if (orgId != nOrgId) {
            // 需要更新已导入的所有数据
            PageData pageData = new PageData();
            pageData.put("user", sysUser.getId());
            remoteUserService.updateRecordExtflag(pageData);
        }
        return JsonObj.success("修改成功！");
    }

    /**
     * 删除用户
     */
    @Override
    public void deleteSysUser(Long[] id) {
        if (ArrayUtils.contains(id, 1L)) {
            throw new IllegalArgumentException("系统管理员不能删除");
        }
        sysUserMapper.deleteSysUser(id);
        // 扩展信息表中的数据，在删除用户后，不做处理
    }

    /**
     * 查询机构下的所有用户 一条数据有自己本身的主键和父主键
     * <p>
     * 新建的用户存的是每条机构的主键
     * <p>
     * 要求就是点机构的时候看下面的所有用户
     * <p>
     * 点击的时候把
     * <p>
     * ·主键==>已经是用户表的存的主键了 ·拿到机构主键后   执行sql语句 ==>  id = #{主键} or parentId  = #{主键}
     * <p>
     * 考虑： 机构禁用或者是删除，所以查询语句尽量加上条件
     */
    @Override
    public Map<String, Object> getUserByOrgId(String username,
                                              String status,
                                              String sorter,
                                              Integer currentPage,
                                              Integer pageSize,
                                              Long orgId) {
        //查询用户信息结果
        Map<String, Object> paramMap = new HashMap<>();
        //扔给用户查询的机构主键集合
        List<Long> ids = new ArrayList<>();
        //筛选完的实体集合
        List<SysOrg> list = new ArrayList<>();
        //第一个子集合
        List<SysOrg> o1 = new ArrayList<>();
        //第一个子集合
        List<SysOrg> o2 = new ArrayList<>();

        //得到主键查询的实体
        SysOrg selectById = sysOrgMapper.selectById(orgId);
        //得到机构集合
        List<SysOrg> orgList = sysOrgMapper.getOrgIdByAncestors();

        //得到父主键的值，判断是否为所有数据的父类
        Long parentId = selectById.getParentId();
        //条件机构集合
        if (StringUtils.isNotEmpty(orgId.toString())) {
            if (!parentId.equals(0L)) {
                if (!org.springframework.util.CollectionUtils.isEmpty(orgList)) {
                    orgList
                        .parallelStream()
                        .parallel()
                        .forEach(sysOrg -> {
                            if (!parentId.equals(0L)) {
                                //得到此主键的第一个子集合
                                if (sysOrg
                                    .getParentId()
                                    .equals(orgId)) {
                                    o1.add(sysOrg);
                                }
                            }
                        });
                    list.addAll(o1);
                }
                if (!org.springframework.util.CollectionUtils.isEmpty(o1)) {
                    o1
                        .parallelStream()
                        .parallel()
                        .forEach(org -> {
                            orgList
                                .parallelStream()
                                .forEach(sysOrg -> {
                                    //得到此主键的子集合
                                    if (org
                                        .getId()
                                        .equals(sysOrg.getParentId())) {
                                        o2.add(sysOrg);
                                    }
                                });
                        });
                    list.addAll(o2);
                }
            }
        }
        if (!org.springframework.util.CollectionUtils.isEmpty(list)) {
            list
                .parallelStream()
                .parallel()
                .forEach(org -> {
                    ids.add(org.getId());
                });
        } else {
            if (parentId.equals(0L)) {
                //得到此主键的第一个子集合
                orgList
                    .parallelStream()
                    .parallel()
                    .forEach(org -> {
                        ids.add(org.getId());
                    });
            } else {
                ids.add(orgId);
            }
        }

        //TODO:问题出在点击的机构下面的用户消失，所以将用户点击的orgId放入ids中
        ids.add(orgId);

        paramMap.put("idList", ids);
        paramMap.put("username", username);
        paramMap.put("tenantCode",
                     CurrentUserUtils
                         .getOAuth2AuthenticationDetailsInfo()
                         .get("tenantCode"));// 当前用户的租户编码
        if (StringUtils.isNotBlank(status)) {
            String[] statusArray = status.split(",");
            paramMap.put("statusList", (Short[]) ConvertUtils.convert(statusArray, Short.class));
        }
        if (StringUtils.isNotBlank(sorter)) {
            String sort = sorter.substring(0, sorter.lastIndexOf('_'));
            String sequence =
                "ascend".equals(sorter.substring(sorter.lastIndexOf('_') + 1)) ? "ASC" : "DESC";
            paramMap.put("sort", sort);
            paramMap.put("sequence", sequence);
        } else {
            paramMap.put("sort", "createTime");
            paramMap.put("sequence", "DESC");
        }
        Page<Object> page = PageHelper.startPage(currentPage, pageSize);
        List<LinkedHashMap<String, Object>> resultList = sysUserMapper.getUserByOrgIdList(paramMap);

        String roleData = sysRoleMapper.queryRoleData("sysuser",
                                                      CurrentUserUtils
                                                          .getOAuth2AuthenticationDetailsInfo()
                                                          .get("name"));
        String[] roleDataArray = roleData == null ? null : roleData.split(",");
        if (roleDataArray != null && roleDataArray.length > 0) {// 处理数据权限
            return PaginationBuilder.buildResult(CollectionUtils.convertFilterList(resultList,
                                                                                   roleDataArray),
                                                 page.getTotal(),
                                                 currentPage,
                                                 pageSize);
        } else {
            return PaginationBuilder.buildResult(resultList,
                                                 page.getTotal(),
                                                 currentPage,
                                                 pageSize);
        }
    }

    @Override
    public void changeStatus(SysUser sysUser) {
        sysUserMapper.changeStatus(sysUser);
    }

    @Override
    public JsonObj selectById(Long id) {
        LinkedHashMap<String, Object> user = sysUserMapper.selectByUserId(id);

        Long tmp = (Long) user.get("orgId");
        if (tmp != null) {
            user.put("orgId", tmp.toString());
        }

        Map<String, Object> map = new LinkedHashMap<>();
        map.put("sysUser", user);
        return JsonObj.success(map);
    }

    @Override
    public String selectOrgIdByUserId(String id) {
        return sysUserMapper.selectOrgIdByUserId(id);
    }
}
